package one.stand.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import one.stand.aop.ApiController;
import one.stand.entity.TokenEntity;
import one.stand.enums.ResultEnum;
import one.stand.exception.*;
import one.stand.feign.CrmFegin;
import one.stand.feign.LoginFegin;
import one.stand.model.ResultModel;
import one.stand.request.BusinessCardRequest;
import one.stand.request.TokenRequest;
import one.stand.util.IpUtil;
import one.stand.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Administrator
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    protected static final Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
    @Autowired
    @Lazy
    private CrmFegin crmFegin;
    @Autowired
    @Lazy
    private LoginFegin loginFegin;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        httpServletResponse.setHeader("Content-type", "application/json;charset=UTF-8");
        StringBuffer requestURL = httpServletRequest.getRequestURL();
        log.info("前置拦截器1 preHandle： 请求的uri为：" + requestURL.toString());
        try {
            String ip = IpUtil.getIpAddr(httpServletRequest);
            String token = httpServletRequest.getHeader("token");
            String compamyKey = httpServletRequest.getHeader("companyKey");
            StringBuffer stringBuffer = new StringBuffer(ip).append(requestURL).append(JSON.toJSONString(httpServletRequest.getParameterMap()));
            if (redisUtil.requestLock(stringBuffer.toString())) {
                throw new FrequentlyException();
            }
            TokenRequest request = new TokenRequest();
            request.setIp(ip);
            request.setToken(token);
            if (o instanceof HandlerMethod) {
                HandlerMethod h = (HandlerMethod) o;
                ApiController apiController = h.getMethodAnnotation(ApiController.class);
                if (apiController != null) {
                    //验证是否需要进行登陆校验
                    if (apiController.isLogin()) {
                        if (StringUtils.isEmpty(token)) {
                            //未获取到token抛出异常
                            throw new LoginException("token请求头未设置");
                        }

                        ResultModel<TokenEntity> result = loginFegin.getLoginInfo(token);
                        if (result == null) {
                            throw new LoginException("登录失败");
                        } else if (result.getData() == null) {
                            throw new LoginException("登录失败：" + result.getMessage());
                        }
                        TokenEntity tokenEntity = result.getData();
                        if (null == tokenEntity) {
                            throw new LoginException("Token信息缓存不存在或者失效");
                        }

                        log.info("token信息为: {}", JSON.toJSONString(tokenEntity));
                        if (!tokenEntity.getCompanyKey().equals(compamyKey)) {
                            log.info("companyKey不同：{}--{}", tokenEntity.getCompanyKey(), compamyKey);
                            throw new ParamException(String.format("登陆companyKey不同(%s)", tokenEntity.getCompanyKey()));
                        }

                        if (apiController.card()) {
                            if (null == tokenEntity.getMyCardId()) {
                                throw new CardException("Token缓存信息中的名片ID为空");
                            }
                            if (tokenEntity.getMyCardId() < 0) {
                                throw new CardException("Token缓存信息中的名片ID不合法");
                            }
                            ResultModel resultModel = crmFegin.verifyExpired(new BusinessCardRequest() {{
                                setCardId(tokenEntity.getMyCardId());
                            }});
                            log.info("名片服务验证：{}", JSON.toJSONString(resultModel));
                            if (!resultModel.isSuccess()) {
                                throw new CardNumServiceException("卡片服务校验失败:" + resultModel.getMessage());
                            }
                        }
                        if (apiController.company()) {
                            if (null == tokenEntity.getCId()) {
                                throw new CompanyException("Token缓存信息中的公司ID为空");
                            }
                            if (tokenEntity.getCId() < 0) {
//                                throw new CompanyException("Token缓存信息中的公司ID不合法");
                                //新用户进入后提示错误 bug,已经关闭 2020-04-07
//                                throw new CompanyException("Token缓存信息中的公司ID不合法");
                                log.info("新用户进入USER:Token缓存信息中的公司ID不合法");
                            }
                        }
                        if (apiController.isBoss()) {
                            if (null == tokenEntity.getRoleId())
                                throw new BossException("Token缓存信息中的RoleId为空");
                            if (tokenEntity.getRoleId() <= 0)
                                throw new BossException("Token缓存信息中的RoleId不合法");
                        }
                        BeanUtils.copyProperties(tokenEntity, request);

                        if (apiController.isParam()) {
                            Object object = httpServletRequest.getAttribute("request");
                            String attribute = null;
                            JSONObject data;
                            if (null != object) {
                                attribute = JSON.toJSONString(object);
                            }
                            if (StringUtils.isEmpty(attribute)) {
                                data = new JSONObject();
                            } else {
                                data = JSONObject.parseObject(attribute);
                            }
                            if (null == data) {
                                data = new JSONObject();
                            }
                            data.put("token", token);
                            data.put("id", request.getId());
                            data.put("ip", request.getIp());
                            data.put("cId", request.getCId());
                            data.put("roleId", request.getRoleId());
                            data.put("myCardId", request.getMyCardId());
                            data.put("loginProgramName", request.getLoginProgramName());
                            data.put("logintime", request.getLogintime());
                            data.put("companyKey", request.getCompanyKey());
                            httpServletRequest.setAttribute("request", data.toJavaObject(apiController.paramClass()));
                        }

                    }

                }
            }
            httpServletRequest.setAttribute("tokenRequest", request);
            return true;
        } catch (FrequentlyException fe) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.FREQUENTLY, fe.getMessage());
            return false;
        } catch (LoginException l) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.NO_LOGIN, l.getMessage());
            return false;
        } catch (CompanyException ce) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.NO_COMPANY, ce.getMessage());
            return false;
        } catch (CardException cee) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.NO_ROLE, cee.getMessage());
            return false;
        } catch (CardNumServiceException cnse) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.CARD_OVERDUE, cnse.getMessage());
            return false;
        } catch (BossException be) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.NO_BOSS, be.getMessage());
            return false;
        } catch (Exception e) {
            ResultModel.returnJson(httpServletResponse, ResultEnum.ERROR, e.getMessage());
            log.info("登录拦截系统异常：{}", e);
            return false;
        }
    }
}
